package ua.kharkov.khpi.tarasenko.bach.dao.mysql.assocrules;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import ua.kharkov.khpi.tarasenko.bach.analysis.tnr.RuleG;
import ua.kharkov.khpi.tarasenko.bach.core.db.DBUtils;
import ua.kharkov.khpi.tarasenko.bach.core.db.EShopDataStoreException;
import ua.kharkov.khpi.tarasenko.bach.core.utils.RuleUtils;
import ua.kharkov.khpi.tarasenko.bach.dao.core.assocrules.AssocRulesDAO;

/**
 * @author oleksandr
 * 
 */
public class AssocRulesDAOImpl implements AssocRulesDAO {

	private static final String TABLE_RULES = "association_rule";

	private static final String QUERY_FIND_CONSEQUENT_BY_ANTECEDENT = "SELECT CONSEQUENT, SUPPORT FROM " + TABLE_RULES + " WHERE ANTECEDENT = ? ORDER BY SUPPORT";
	private static final String QUERY_ADD_RULE = "INSERT INTO " + TABLE_RULES
			+ "(ANTECEDENT, CONSEQUENT, SUPPORT)" + " VALUES(?, ?, ?)";

	private static final String QUERY_DELETE_ALL_RULES = "DELETE FROM "
			+ TABLE_RULES;
	private static final String QUERY_GET_NUMBER_OF_RULES = "SELECT count(*) as count FROM "
			+ TABLE_RULES;

	private Connection conn;

	public AssocRulesDAOImpl(Connection conn) throws EShopDataStoreException {
		if (conn == null) {
			throw new EShopDataStoreException("Connection is null!");
		}
		this.conn = conn;
	}

	@Override
	public void saveRule(RuleG rule) throws EShopDataStoreException {
		PreparedStatement ps = null;

		String antec = RuleUtils.getAntecedent(rule);
		String cons = RuleUtils.getConsequent(rule);

		try {
			ps = conn.prepareStatement(QUERY_ADD_RULE);
			ps.setString(1, antec);
			ps.setString(2, cons);
			ps.setInt(3, rule.count);

			ps.executeUpdate();

			ps.close();
		} catch (SQLException e) {
			throw new EShopDataStoreException(
					"Error occurred during saving rule", e);
		} finally {
			DBUtils.close(null, ps);
		}
	}

	@Override
	public List<String> getConsequentsByAntecedent(String antec) throws EShopDataStoreException {
		List<String> conseqsString = new ArrayList<String>();

		PreparedStatement ps = null;
		ResultSet rs = null;

		try {
			ps = conn.prepareStatement(QUERY_FIND_CONSEQUENT_BY_ANTECEDENT);
			ps.setString(1, antec);
			rs = ps.executeQuery();

			while (rs.next()) {
				conseqsString.add(rs.getString("CONSEQUENT"));
			}

			DBUtils.close(rs, ps);
		} catch (SQLException e) {
			throw new EShopDataStoreException(
					"Error occurred during getting consequents by antecedent", e);
		} finally {
			DBUtils.close(rs, ps);
		}
		return conseqsString;
	}

	@Override
	public void deleteAllRules() throws EShopDataStoreException {
		PreparedStatement ps = null;

		try {
			ps = conn.prepareStatement(QUERY_DELETE_ALL_RULES);
			ps.executeUpdate();

		} catch (SQLException e) {
			throw new EShopDataStoreException(
					"Error occurred during deleting all rules", e);
		} finally {
			DBUtils.close(null, ps);
		}
	}

	@Override
	public int getNumberOfRules() throws EShopDataStoreException {
		int number = 0;

		PreparedStatement ps = null;
		ResultSet rs = null;

		try {
			ps = conn.prepareStatement(QUERY_GET_NUMBER_OF_RULES);
			rs = ps.executeQuery();

			if (rs.next()) {
				number = rs.getInt(1);
			}

			DBUtils.close(rs, ps);
		} catch (SQLException e) {
			throw new EShopDataStoreException(
					"Error occurred during getting number of rules", e);
		} finally {
			DBUtils.close(rs, ps);
		}
		return number;
	}
}